home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / msysjour / vol06 / 03 / wintro6 / graph.c < prev    next >
C/C++ Source or Header  |  1991-05-01  |  20KB  |  616 lines

  1. /*=================================================================*/
  2. /*                                                                 */
  3. /* File    : GRAPH.C                                               */
  4. /*                                                                 */
  5. /* Purpose : Render the graphs for the stock charts                */
  6. /*                                                                 */
  7. /* History :                                                       */
  8. /*                                                                 */
  9. /* (C) Copyright 1989,1990 Marc Adler/Magma Systems                */
  10. /*=================================================================*/
  11.  
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <windows.h>
  15. #include "stock.h"
  16.  
  17. void FAR PASCAL HandleSelectionState(LPDRAWITEMSTRUCT lpdis,
  18.                                      int inflate);
  19. void FAR PASCAL HandleFocusState(LPDRAWITEMSTRUCT lpdis,
  20.                                      int inflate);
  21. void FAR PASCAL DrawEntireItem(LPDRAWITEMSTRUCT lpdis,
  22.                                      int inflate);
  23.  
  24.  
  25. BOOL FAR PASCAL
  26. GraphOptionsDlgProc(hDlg, message, wParam, lParam)
  27.   HWND hDlg;
  28.   unsigned message;
  29.   WORD wParam;
  30.   LONG lParam;
  31. {
  32.   int         iPen; 
  33.   char        szBuf[80];
  34.   static HANDLE      hStockInfo = NULL;
  35.   static LPSTOCKINFO lpStockInfo = (LPSTOCKINFO) NULL;
  36.   LPGRAPHINFO lpGraphInfo;
  37.   HWND        hWnd;
  38.   BOOL        bTranslated;
  39.  
  40.  
  41.   switch (message)
  42.   {
  43.     case WM_INITDIALOG :
  44.       if ((hStockInfo = (HANDLE) lParam) == NULL)
  45.       {
  46.         EndDialog(hDlg, IDCANCEL);
  47.         return TRUE;
  48.       }
  49.  
  50.       if ((lpStockInfo = (LPSTOCKINFO) GlobalLock(hStockInfo)) == NULL)
  51.       {
  52.         EndDialog(hDlg, IDCANCEL);
  53.         return TRUE;
  54.       }
  55.   
  56.       lpGraphInfo = &lpStockInfo->StockFile.graphinfo;
  57.  
  58.       /*
  59.         If the ticks array has some memory allocated to it, it means
  60.         that we are dealing with an existing stock. If not, then we
  61.         are creating a new stock.
  62.       */
  63.       if (lpStockInfo->hTicks != NULL)
  64.       {
  65.         SetDlgItemText(hDlg, ID_SYMBOL, 
  66.                       lpStockInfo->StockFile.szStock);
  67.         SetDlgItemInt(hDlg, ID_MINPRICE,
  68.                       (int) lpGraphInfo->dwMinPrice, FALSE);
  69.         SetDlgItemInt(hDlg, ID_MAXPRICE,
  70.                       (int) lpGraphInfo->dwMaxPrice, FALSE);
  71.         SetDlgItemInt(hDlg, ID_FACTOR,
  72.                       (int)lpGraphInfo->dwScaleFactor,FALSE);
  73.         SetDlgItemInt(hDlg, ID_TICKINT,
  74.                       (int)lpGraphInfo->dwTickInterval,FALSE);
  75.         SetDlgItemInt(hDlg, ID_DENOMINATOR,
  76.                       (int) lpGraphInfo->iDenominator, FALSE);
  77.  
  78.         if (lpStockInfo->dwFlags & STATE_HAS_VGRID)
  79.           CheckDlgButton(hDlg, ID_VERTGRID, TRUE);
  80.         if (lpStockInfo->dwFlags & STATE_HAS_HGRID)
  81.           CheckDlgButton(hDlg, ID_HORZGRID, TRUE);
  82.  
  83.         EnableWindow(GetDlgItem(hDlg, ID_SYMBOL), FALSE);
  84.       }
  85.       else
  86.       {
  87.         lpGraphInfo->iGridPen = 0;
  88.       }
  89.  
  90.  
  91.       /* 
  92.         Fill the listbox with pen ids 
  93.       */ 
  94.       for (iPen = 0;  iPen < PS_NULL;  iPen++) 
  95.         SendDlgItemMessage(hDlg, ID_GRIDSTYLE, CB_ADDSTRING, 0,
  96.                               (LONG) iPen); 
  97.       SendDlgItemMessage(hDlg,ID_GRIDSTYLE,CB_SETCURSEL,
  98.                               lpGraphInfo->iGridPen,0L);
  99.       return TRUE;
  100.  
  101.  
  102.     case WM_MEASUREITEM : 
  103.     { 
  104.       LPMEASUREITEMSTRUCT lpMI = (LPMEASUREITEMSTRUCT)(LPSTR)lParam;
  105.       lpMI->itemWidth  = 42; 
  106.       lpMI->itemHeight = 20; 
  107.       break; 
  108.     } 
  109.  
  110.     case WM_DRAWITEM : 
  111.     { 
  112.       LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) (LPSTR) lParam; 
  113.  
  114.       if (lpdis->itemID == -1)
  115.       {
  116.         HandleFocusState(lpdis, -5);
  117.         break;
  118.       }
  119.  
  120.       switch (lpdis->itemAction) 
  121.       { 
  122.         case ODA_DRAWENTIRE: 
  123.           DrawEntireItem(lpdis, -4); 
  124.           break; 
  125.  
  126.         case ODA_SELECT: 
  127.           HandleSelectionState(lpdis, 0); 
  128.           break; 
  129.  
  130.         case ODA_FOCUS: 
  131.           HandleFocusState(lpdis, -2); 
  132.           break; 
  133.       } 
  134.  
  135.       break; 
  136.     } 
  137.  
  138.  
  139.     case WM_COMMAND :
  140.       switch (wParam)
  141.       {
  142.         case IDOK :
  143.           lpGraphInfo = &lpStockInfo->StockFile.graphinfo;
  144.  
  145.           if (lpStockInfo->hTicks == NULL)
  146.           {
  147.             GetDlgItemText(hDlg, ID_SYMBOL, szBuf, sizeof(szBuf));
  148.             if (*szBuf == '\0')
  149.             {
  150.               MessageBox(hWndMain,
  151.                          "You must fill in the name of the stock.",
  152.                          "Error", MB_OK);
  153.               return TRUE;
  154.             }
  155.             strcat(szBuf, ".STO");
  156.             lstrcpy(lpStockInfo->szFileName, szBuf);
  157.  
  158.             lpStockInfo->StockFile.dwMagic = MAGIC_COOKIE;
  159.             if ((lpStockInfo->hTicks = GlobalAlloc(GMEM_MOVEABLE, 
  160.                                        (DWORD) sizeof(TICK) * 64)) == NULL)
  161.             {
  162.               MessageBox(hWndMain, "Can't allocate the ticker array",
  163.                                    "Error", MB_OK);
  164.               goto bye;
  165.             }
  166.             lpStockInfo->nTicksAllocated = 64;
  167.             lpStockInfo->StockFile.nTicks = 0;
  168.  
  169.             /*
  170.               Create a window for this guy
  171.             */
  172.             hWnd = lpStockInfo->hWnd = 
  173.                   GraphCreateWindow((LPSTR) szBuf);
  174.             SetWindowWord(lpStockInfo->hWnd, 0, hStockInfo);
  175.             lpStockInfo->dwFlags |= STATE_DIRTY;
  176.           }
  177.  
  178.           GetDlgItemText(hDlg, ID_SYMBOL,
  179.                          lpStockInfo->StockFile.szStock,
  180.                          sizeof(lpStockInfo->StockFile.szStock));
  181.           lpGraphInfo->dwMinPrice = 
  182.               GetDlgItemLong(hDlg, ID_MINPRICE,
  183.                             (BOOL FAR *) &bTranslated, FALSE);
  184.           lpGraphInfo->dwMaxPrice = 
  185.               GetDlgItemLong(hDlg, ID_MAXPRICE,
  186.                             (BOOL FAR *) &bTranslated, FALSE);
  187.           lpGraphInfo->dwScaleFactor = 
  188.               GetDlgItemLong(hDlg, ID_FACTOR,
  189.                             (BOOL FAR *) &bTranslated, FALSE);
  190.           lpGraphInfo->dwTickInterval = 
  191.               GetDlgItemLong(hDlg, ID_TICKINT,
  192.                             (BOOL FAR *) &bTranslated, FALSE);
  193.           lpGraphInfo->iDenominator = 
  194.               GetDlgItemInt(hDlg, ID_DENOMINATOR,
  195.                             (BOOL FAR *) &bTranslated, FALSE);
  196.           lpGraphInfo->iGridPen = (WORD)
  197.              SendDlgItemMessage(hDlg,ID_GRIDSTYLE,CB_GETCURSEL,0,0L);
  198.  
  199.           lpStockInfo->dwFlags &= ~(STATE_HAS_VGRID|STATE_HAS_HGRID);
  200.           if (IsDlgButtonChecked(hDlg, ID_VERTGRID))
  201.             lpStockInfo->dwFlags |= STATE_HAS_VGRID;
  202.           if (IsDlgButtonChecked(hDlg, ID_HORZGRID))
  203.             lpStockInfo->dwFlags |= STATE_HAS_HGRID;
  204.  
  205. bye:
  206.           InvalidateRect(lpStockInfo->hWnd, (LPRECT) NULL, FALSE);
  207.           GlobalUnlock(hStockInfo);
  208.           EndDialog(hDlg, IDOK);
  209.           break;
  210.  
  211.         case IDCANCEL:
  212.           GlobalUnlock(hStockInfo);
  213.           EndDialog(hDlg, IDCANCEL);
  214.           break;
  215.       }
  216.       return TRUE;
  217.  
  218.   } /* end switch (message) */
  219.  
  220.   return FALSE;
  221. }
  222.  
  223.  
  224. /**************************************************************************** 
  225.  *                                                                          * 
  226.  *  FUNCTION   : HandleSelectionState(LPDRAWITEMSTRUCT, int)                * 
  227.  *                                                                          * 
  228.  *  PURPOSE    : Handles a change in an item selection state. If an item is * 
  229.  *               selected, a black rectangular frame is drawn around that   * 
  230.  *               item; if an item is de-selected, the frame is removed.     * 
  231.  *                                                                          * 
  232.  *  COMMENT    : The black selection frame is slightly larger than the gray * 
  233.  *               focus frame so they won't paint over each other.           * 
  234.  *                                                                          * 
  235.  ****************************************************************************/ 
  236. void FAR PASCAL HandleSelectionState(lpdis, inflate) 
  237.   LPDRAWITEMSTRUCT  lpdis; 
  238.   int               inflate; 
  239.   HBRUSH hbr = (lpdis->itemState & ODS_SELECTED) ? 
  240.                   GetStockObject(BLACK_BRUSH)    :
  241.                   CreateSolidBrush(GetSysColor(COLOR_WINDOW)); 
  242.   FrameRect(lpdis->hDC, (LPRECT) &lpdis->rcItem, hbr); 
  243.   DeleteObject (hbr); 
  244.  
  245.  
  246. /**************************************************************************** 
  247.  *                                                                          * 
  248.  *  FUNCTION   : HandleFocusState(LPDRAWITEMSTRUCT, int)                    * 
  249.  *                                                                          * 
  250.  *  PURPOSE    : Handle a change in item focus state. If an item gains the  * 
  251.  *               input focus, a gray rectangular frame is drawn around that * 
  252.  *               item; if an item loses the input focus, the gray frame is  * 
  253.  *               removed.                                                   * 
  254.  *                                                                          * 
  255.  *  COMMENT    : The gray focus frame is slightly smaller than the black    * 
  256.  *               selection frame so they won't paint over each other.       * 
  257.  *                                                                          * 
  258.  ****************************************************************************/ 
  259. void FAR PASCAL HandleFocusState(lpdis, inflate) 
  260.   LPDRAWITEMSTRUCT  lpdis; 
  261.   int      inflate; 
  262.   RECT  rc; 
  263.   HBRUSH  hbr; 
  264.  
  265.   /* Resize rectangle to place focus frame between the selection 
  266.    * frame and the item. 
  267.    */ 
  268.   CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem); 
  269.   InflateRect ((LPRECT)&rc, inflate, inflate); 
  270.  
  271.   if (lpdis->itemState & ODS_FOCUS) 
  272.     /* gaining input focus -- paint a gray frame */ 
  273.     hbr = GetStockObject(GRAY_BRUSH); 
  274.   else 
  275.     /* losing input focus -- remove (paint over) frame */ 
  276.     hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW)); 
  277.  
  278.   FrameRect(lpdis->hDC, (LPRECT)&rc, hbr); 
  279.   DeleteObject (hbr); 
  280.  
  281. /******************************************************************** 
  282.  *                                                                  * 
  283.  *  FUNCTION   : DrawEntireItem(LPDRAWITEMSTRUCT, int)              * 
  284.  *                                                                  * 
  285.  *  PURPOSE    : Draws an item and frames it with a selection frame *
  286.                  and/or a focus frame when appropriate.             * 
  287.  *                                                                  * 
  288.  *******************************************************************/ 
  289. void FAR PASCAL DrawEntireItem(lpdis, inflate) 
  290.   LPDRAWITEMSTRUCT  lpdis; 
  291.   int      inflate; 
  292.   RECT   rc; 
  293.   HANDLE hOldPen; 
  294.   HPEN   hPen; 
  295.  
  296.   if (lpdis->itemData < 0)
  297.     return;
  298.  
  299.   /* Resize rectangle to leave space for frames */ 
  300.   CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem); 
  301.   InflateRect ((LPRECT)&rc, inflate, inflate); 
  302.  
  303.   if (lpdis->itemState & ODS_FOCUS) 
  304.     hPen = CreatePen((int)lpdis->itemData, 1, RGB(0xFF, 0xFF, 0xFF)); 
  305.   else
  306.     hPen = CreatePen((int) lpdis->itemData, 1, RGB(0, 0, 0)); 
  307.   hOldPen = SelectObject(lpdis->hDC, hPen); 
  308.  
  309.   MoveTo(lpdis->hDC, rc.left,  rc.top + (rc.bottom - rc.top) / 2); 
  310.   LineTo(lpdis->hDC, rc.right, rc.top + (rc.bottom - rc.top) / 2); 
  311.  
  312.   SelectObject(lpdis->hDC, hOldPen); 
  313.   DeleteObject(hPen); 
  314.  
  315.   /* Draw or erase appropriate frames */ 
  316.   HandleSelectionState(lpdis, inflate + 4); 
  317.   HandleFocusState(lpdis, inflate + 2); 
  318.  
  319.  
  320. int PASCAL GraphWndPaint(HWND hWnd, HDC hDC, LPSTOCKINFO lpStockInfo, BOOL bPrinting)
  321. {
  322.   RECT         r;
  323.   int          i, x, y;
  324.   int          xGraph, yGraph;
  325.   LPTICK       lpTick;
  326.   int          rangeHigh,
  327.                rangeLow,
  328.                xPixelsPerDate,
  329.                yTickInterval;
  330.   int          yAxisStart, xAxisStart;
  331.   HANDLE       hOldPen;
  332.   HPEN         hPen;
  333.   HBRUSH       hBrush;
  334.   HFONT        hFont, hOldFont;
  335.   TEXTMETRIC   tm;
  336.   char         szBuf[80];
  337.  
  338.   if (lpStockInfo->StockFile.nTicks == 0)
  339.     return TRUE;
  340.  
  341.   if ((lpTick = (LPTICK) GlobalLock(lpStockInfo->hTicks)) == NULL)
  342.     return TRUE;
  343.  
  344.  
  345.   /*
  346.     Get the client dimensions of the current stock window and figure
  347.     out the width and height of the graph.
  348.   */
  349.   if (bPrinting)
  350.   {
  351.     yGraph = GetDeviceCaps(hDC, VERTRES);
  352.     xGraph = GetDeviceCaps(hDC, HORZRES);
  353.   }
  354.   else
  355.   {
  356.     GetClientRect(hWnd, (LPRECT) &r);
  357.     yGraph = r.bottom - r.top;
  358.     xGraph = r.right - r.left;
  359.   }
  360.  
  361.   /*
  362.     Erase the background to the desired color
  363.   */
  364.   if (!bPrinting)
  365.   {
  366.     hBrush = CreateSolidBrush(lpStockInfo->graphAttrs.clrBackground);
  367.     FillRect(hDC, (LPRECT) &r, hBrush);
  368.     DeleteObject(hBrush);
  369.   }
  370.  
  371.   /*
  372.     Get the low and high range into local variables.
  373.   */
  374.   rangeHigh = (int) lpStockInfo->StockFile.graphinfo.dwMaxPrice;
  375.   rangeLow  = (int) lpStockInfo->StockFile.graphinfo.dwMinPrice;
  376.   if ((yTickInterval = 
  377.         (int) lpStockInfo->StockFile.graphinfo.dwTickInterval) < 1)
  378.     yTickInterval = 1;
  379.  
  380.   /*
  381.     Get the metrics of the current font.
  382.   */
  383.   hOldFont = NULL;
  384.   if (lpStockInfo->graphAttrs.hFont)
  385.     hOldFont = SelectObject(hDC, lpStockInfo->graphAttrs.hFont);
  386.   GetTextMetrics(hDC, (LPTEXTMETRIC) &tm);
  387.  
  388.  
  389.   /*
  390.     Set up the mapping mode. Y-axis points up and X-axis points right.
  391.   */
  392.   SetMapMode(hDC, lpStockInfo->graphAttrs.iMappingMode);
  393.   SetWindowExt(hDC,  xGraph, yGraph);
  394.   SetViewportExt(hDC, xGraph, -yGraph);
  395.   SetViewportOrg(hDC, 0, yGraph);
  396.  
  397.   sprintf(szBuf, "%d", rangeHigh);
  398.   yAxisStart = strlen(szBuf) * (tm.tmAveCharWidth + 1);
  399.   xAxisStart = tm.tmHeight + (tm.tmHeight/2);
  400.   xPixelsPerDate = xGraph / lpStockInfo->StockFile.nTicks;
  401.  
  402.   /*
  403.     Set the background drawing mode to TRANSPARENT so that the spaces
  404.     in between the letters and grid lines get filled with the
  405.     background color.
  406.   */
  407.   SetBkMode(hDC, TRANSPARENT);
  408.  
  409.   /*
  410.     Draw the axises. First the Y-axis, then the X-axis.
  411.   */
  412.   MoveTo(hDC, yAxisStart, xAxisStart);
  413.   LineTo(hDC, yAxisStart, yGraph);
  414.   MoveTo(hDC, yAxisStart, xAxisStart);
  415.   LineTo(hDC, xGraph,     xAxisStart);
  416.  
  417.   /*
  418.     Draw the hash marks for the x-axis
  419.   */
  420.   for (i = 1;  i < lpStockInfo->StockFile.nTicks;  i++)
  421.   {
  422.     int x = i * xPixelsPerDate + yAxisStart;
  423.     int iTextLen;
  424.     MoveTo(hDC, x, xAxisStart-2);
  425.     LineTo(hDC, x, xAxisStart+2);
  426.     sprintf(szBuf, "%d", i+1);
  427.     iTextLen = strlen(szBuf) * tm.tmAveCharWidth;
  428.     /*
  429.       Output the x-axis text centered over the hash mark
  430.     */
  431.     TextOut(hDC, x-(iTextLen>>1), xAxisStart-2, szBuf,strlen(szBuf));
  432.   }
  433.  
  434.   /*
  435.     Draw the hash marks for the y-axis
  436.   */
  437.   for (i = rangeLow;  i <= rangeHigh;
  438.        i += yTickInterval)
  439.   {
  440.     int y = (int) ((long) (i-rangeLow) * (long) (yGraph-xAxisStart) /
  441.                            (rangeHigh-rangeLow) + xAxisStart);
  442.     if (i > rangeLow)
  443.     {
  444.       MoveTo(hDC, yAxisStart-4, y);
  445.       LineTo(hDC, yAxisStart+4, y);
  446.     }
  447.     sprintf(szBuf, "%d", i);
  448.     TextOut(hDC, 0, y + (tm.tmHeight >> 1), szBuf, strlen(szBuf));
  449.   }
  450.  
  451.  
  452.   /*
  453.     Now draw the horizontal and vertical grid lines.
  454.   */
  455.   hPen = CreatePen(lpStockInfo->StockFile.graphinfo.iGridPen, 1, 
  456.                    lpStockInfo->graphAttrs.clrPen);
  457.   hOldPen = SelectObject(hDC, hPen);
  458.  
  459.   if (lpStockInfo->dwFlags & STATE_HAS_VGRID)
  460.   {
  461.     for (i = 0;  i < lpStockInfo->StockFile.nTicks;  i++)
  462.     {
  463.       int x = (i+1) * xPixelsPerDate + yAxisStart;
  464.       MoveTo(hDC, x, xAxisStart);
  465.       LineTo(hDC, x, yGraph);
  466.     }
  467.   }
  468.  
  469.   if (lpStockInfo->dwFlags & STATE_HAS_HGRID)
  470.   {
  471.     for (i = rangeLow + yTickInterval;  i <= rangeHigh;
  472.          i += yTickInterval)
  473.     {
  474.       int y = (int) ((long) (i-rangeLow) * (long) (yGraph-xAxisStart) /
  475.                         (rangeHigh - rangeLow) + xAxisStart);
  476.       MoveTo(hDC, yAxisStart, y);
  477.       LineTo(hDC, xGraph, y);
  478.     }
  479.   }
  480.  
  481.   SelectObject(hDC, hOldPen);
  482.   DeleteObject(hPen);
  483.  
  484.  
  485.   /*
  486.     Figure out how many pixels wide each entry should be. This is
  487.     equal to the width of the graph divided by the number of ticks 
  488.     to be plotted.
  489.   */
  490.   MoveTo(hDC, yAxisStart, (int) (xAxisStart + 
  491.           (long) (lpTick[0].price - rangeLow) * 
  492.                                    (long) yGraph / (rangeHigh - rangeLow)));
  493.   if (lpStockInfo->StockFile.nTicks == 1)
  494.   {
  495.     Ellipse(hDC, yAxisStart-2, xAxisStart-2, 
  496.                  yAxisStart+2, xAxisStart+2);
  497.   }
  498.   else
  499.   {
  500.     for (i = 1;  i < lpStockInfo->StockFile.nTicks;  i++)
  501.     {
  502.       int x = i * xPixelsPerDate;
  503.       int y = (int) ((lpTick[i].price - rangeLow) * (long) yGraph / 
  504.                                    (rangeHigh-rangeLow));
  505.       LineTo(hDC, x + yAxisStart, y + xAxisStart);
  506.       Ellipse(hDC, x+yAxisStart-2, y+xAxisStart-2, 
  507.                    x+yAxisStart+2, y+xAxisStart+2);
  508.     }
  509.   }
  510.  
  511.  
  512.   if (hOldFont)
  513.     SelectObject(hDC, hOldFont);
  514.   GlobalUnlock(lpStockInfo->hTicks);
  515.   return TRUE;
  516. }
  517.  
  518.  
  519. #include "rainbow.h"
  520.  
  521. BOOL FAR PASCAL GraphColorsDlgProc(hDlg, msg, wParam, lParam)
  522.   HWND hDlg;
  523.   WORD msg;
  524.   WORD wParam;
  525.   LONG lParam;
  526. {
  527.   LPSTOCKINFO lpStockInfo;
  528.   char        szMsg[80];
  529.  
  530.   switch (msg)
  531.   {
  532.     case WM_INITDIALOG:
  533.       /*
  534.          Make sure that there is a current stock information record
  535.          which we can append the ticker onto.
  536.       */
  537.       if (!hCurrStockInfo)
  538.       {
  539.         MessageBox(hDlg, "There is no current stock graph.", 
  540.                          "Error", MB_OK);
  541.         EndDialog(hDlg, FALSE);
  542.         return TRUE;
  543.       }
  544.  
  545.       lpStockInfo = (LPSTOCKINFO) GlobalLock(hCurrStockInfo);
  546.       if (lpStockInfo == NULL)
  547.       {
  548.         MessageBox(hDlg, "GlobalLock returned NULL", "Error", MB_OK);
  549.         EndDialog(hDlg, FALSE);
  550.         return TRUE;
  551.       }
  552.  
  553.       SendDlgItemMessage(hDlg, ID_PENCOLOR,  RM_SETSEL,
  554.                          lpStockInfo->graphAttrs.idxPen, 0L);
  555.       SendDlgItemMessage(hDlg, ID_BACKCOLOR, RM_SETSEL, 
  556.                          lpStockInfo->graphAttrs.idxBackground, 0L);
  557.  
  558.       GlobalUnlock(hCurrStockInfo);
  559.       return TRUE;
  560.  
  561.  
  562.     case WM_COMMAND:
  563.       switch (wParam)
  564.       {
  565.         /*
  566.           The user chose the OK button...
  567.         */
  568.         case IDOK:
  569.           /*
  570.             Get a pointer to the stock info record
  571.           */
  572.           lpStockInfo = (LPSTOCKINFO) GlobalLock(hCurrStockInfo);
  573.           if (lpStockInfo == NULL)
  574.           {
  575.             MessageBox(hDlg, "GlobalLock returned NULL", 
  576.                              "Error", MB_OK);
  577.             EndDialog(hDlg, FALSE);
  578.             break;
  579.           }
  580.  
  581.           lpStockInfo->graphAttrs.idxPen = (WORD)
  582.             SendDlgItemMessage(hDlg, ID_PENCOLOR,  RM_GETSEL, 0,
  583.                     (LONG) (LPSTR) &lpStockInfo->graphAttrs.clrPen);
  584.           lpStockInfo->graphAttrs.idxBackground = (WORD)
  585.             SendDlgItemMessage(hDlg, ID_BACKCOLOR, RM_GETSEL, 0,
  586.                     (LONG) (LPSTR)
  587.                             &lpStockInfo->graphAttrs.clrBackground);
  588.  
  589.           InvalidateRect(lpStockInfo->hWnd, (LPRECT) NULL, FALSE);
  590.           GlobalUnlock(hCurrStockInfo);
  591.           EndDialog(hDlg, TRUE);
  592.           break;
  593.  
  594.  
  595.         /*
  596.           The user chose the CANCEL button....
  597.         */
  598.         case IDCANCEL :
  599.           EndDialog(hDlg, FALSE);
  600.           break;
  601.       }
  602.       return TRUE;
  603.  
  604.     default:
  605.       return FALSE;
  606.   }
  607. }
  608.  
  609.  
  610.